package com.fastjrun.security.authentication.mobile;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fastjrun.security.authentication.exception.ValidateCodeException;
import com.fastjrun.security.properties.SecurityProperties;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.annotation.Resource;
import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.Map;

@Component // 不要少了
public class MobileValidateFilter extends OncePerRequestFilter {

  @Resource private SecurityProperties securityProperties;

  @Autowired AuthenticationFailureHandler customAuthenticationFailureHandler;

  @Override
  protected void doFilterInternal(
      HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
      throws ServletException, IOException {
    // 1. 判断 请求是否为手机登录，且post请求
    if (request.getMethod().equalsIgnoreCase("POST")
        && (request
            .getRequestURI()
            .endsWith(securityProperties.getAuthentication().getMobileLoginUrl()))) {

      try {
        // 校验验证码合法性
        validate(request);
      } catch (AuthenticationException e) {
        // 交给失败处理器进行处理异常
        customAuthenticationFailureHandler.onAuthenticationFailure(request, response, e);
        // 一定要记得结束
        return;
      }
    }

    // 放行
    filterChain.doFilter(request, response);
  }

  private void validate(HttpServletRequest request) {
    // 先获取seesion中的验证码
    String sessionCode =
        (String) request.getSession().getAttribute(MobileConstants.SESSION_KEY_MOBILE_CODE);
    request.getSession().removeAttribute(MobileConstants.SESSION_KEY_MOBILE_CODE);
    String mediaType = request.getContentType();
    if (mediaType != null) {
      if (request.getContentType().equals(MediaType.APPLICATION_JSON_UTF8_VALUE)
          || request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)) {
        ObjectMapper mapper = new ObjectMapper();
        try (InputStream is = request.getInputStream()) {
          Map<String, String> authenticationBean = mapper.readValue(is, Map.class);

          // 获取用户输入的验证码
          String inpuCode = authenticationBean.get("smsCode");
          // 判断是否正确
          if (StringUtils.isBlank(inpuCode)) {
            throw new ValidateCodeException("验证码不能为空");
          }

          if (!inpuCode.equalsIgnoreCase(sessionCode)) {
            throw new ValidateCodeException("验证码输入错误");
          }

          // 获取用户输入的手机号
          String phone = authenticationBean.get("phone");

          // 2. 将手机号保存到session中
          request.getSession().setAttribute(MobileConstants.SESSION_KEY_MOBILE, phone);

        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
}
